/*
 * $Id: WriterCharacterOutputStream.java 113 2013-01-16 06:10:04Z vladimirow@mail.ru $
 * $HeadURL: http://ultralog.googlecode.com/svn/ultralog/tags/release-0.1/src/java/com/google/code/ultralog/writer/WriterCharacterOutputStream.java $
 *
 * This file is a part of ultralog project (http://code.google.com/p/ultralog/).
 * Released under New BSD License.
 */
package com.google.code.ultralog.writer;

import java.io.IOException;
import java.io.Writer;

import com.google.code.ultralog.utils.CharacterOutputStream;
import com.google.code.ultralog.utils.CharacterSequence;

/**
 * An implementation of {@link CharacterOutputStream} that wraps {@link Writer}
 * object.
 *
 * @author Mikhail Vladimirov
 */
public class WriterCharacterOutputStream implements CharacterOutputStream
{
    private final Writer writer;

    /**
     * Create new stream that wraps given {@link Writer} object.
     *
     * @param writer {@link Writer} object to wrap
     */
    public WriterCharacterOutputStream (Writer writer)
    {
        if (writer == null)
            throw new IllegalArgumentException ("Writer is null");

        this.writer = writer;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (char ch)
    {
        try
        {
            writer.write (ch);
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot write to writer", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (char ch1, char ch2)
    {
        try
        {
            writer.write (ch1);
            writer.write (ch2);
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot write to writer", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (char ch1, char ch2, char ch3)
    {
        try
        {
            writer.write (ch1);
            writer.write (ch2);
            writer.write (ch3);
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot write to writer", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (char ch1, char ch2, char ch3, char ch4)
    {
        try
        {
            writer.write (ch1);
            writer.write (ch2);
            writer.write (ch3);
            writer.write (ch4);
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot write to writer", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (char [] buffer, int offset, int length)
    {
        if (buffer == null)
            throw new IllegalArgumentException ("Buffer is null");

        if (offset < 0)
            throw new IllegalArgumentException ("Offset (" + offset + ") < 0");

        if (length < 0)
            throw new IllegalArgumentException ("Length (" + length + ") < 0");

        int bufferLength = buffer.length;
        if (offset + length > bufferLength)
            throw new IllegalArgumentException (
                "Offset (" + offset + ") + length (" + length +
                ") > buffer length (" + bufferLength + ")");

        try
        {
            writer.write (buffer, offset, length);
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot write to writer", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (String string, int offset, int length)
    {
        if (string == null)
            throw new IllegalArgumentException ("String is null");

        if (offset < 0)
            throw new IllegalArgumentException ("Offset (" + offset + ") < 0");

        if (length < 0)
            throw new IllegalArgumentException ("Length (" + length + ") < 0");

        int stringLength = string.length ();
        if (offset + length > stringLength)
            throw new IllegalArgumentException (
                "Offset (" + offset + ") + length (" + length +
                ") > string length (" + stringLength + ")");

        try
        {
            writer.write (string, offset, length);
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot write to writer", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (CharSequence sequence, int offset, int length)
    {
        if (sequence == null)
            throw new IllegalArgumentException ("Sequence is null");

        if (offset < 0)
            throw new IllegalArgumentException ("Offset (" + offset + ") < 0");

        if (length < 0)
            throw new IllegalArgumentException ("Length (" + length + ") < 0");

        int sequenceLength = sequence.length ();
        if (offset + length > sequenceLength)
            throw new IllegalArgumentException (
                "Offset (" + offset + ") + length (" + length +
                ") > sequence length (" + sequenceLength + ")");

        try
        {
            for (int end = offset + length, i = offset; i < end; i++)
                writer.write (sequence.charAt (i));
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot write to writer", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void write (CharacterSequence sequence, int offset, int length)
    {
        if (sequence == null)
            throw new IllegalArgumentException ("Sequence is null");

        if (offset < 0)
            throw new IllegalArgumentException ("Offset (" + offset + ") < 0");

        if (length < 0)
            throw new IllegalArgumentException ("Length (" + length + ") < 0");

        int sequenceLength = sequence.getLength ();
        if (offset + length > sequenceLength)
            throw new IllegalArgumentException (
                "Offset (" + offset + ") + length (" + length +
                ") > sequence length (" + sequenceLength + ")");

        sequence.writeCharactersTo (offset, length, this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void flush ()
    {
        try
        {
            writer.flush ();
        }
        catch (IOException ex)
        {
            throw new RuntimeException ("Cannot flush writer", ex);
        }
    }
}
